#include "container/vector.h"
#include <stdio.h>

#include "unity.h"

void test_VectorInit(void)
{
    uint8_t buf[20];
    cotVector_t vector;

    cotVector_Init(&vector, buf, sizeof(buf), sizeof(int));
    TEST_ASSERT_EQUAL_PTR(buf, vector.pBuf);
    TEST_ASSERT_EQUAL_UINT(sizeof(int), vector.itemSize);
    TEST_ASSERT_EQUAL_UINT(sizeof(buf) / sizeof(int), vector.limit);
    TEST_ASSERT_EQUAL_UINT(0, vector.sIdx);
    TEST_ASSERT_EQUAL_UINT(0, vector.eIdx);
}

void test_VectorAssign(void)
{
    uint8_t buf[20];
    cotVector_t vector;

    cotVector_Init(&vector, buf, sizeof(buf), sizeof(uint32_t));

    uint32_t data = 42;
    cotVector_Push(&vector, &data);
    data = 56;
    cotVector_Push(&vector, &data);
    data = 984;
    cotVector_Push(&vector, &data);
    TEST_ASSERT_EQUAL_UINT(3, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(42, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(984, *(uint32_t *)cotVector_Back(&vector));

    uint32_t arrdata[4] = {125, 656, 4874, 4185};

    cotVector_Assign(&vector, &arrdata, 4);

    TEST_ASSERT_EQUAL_UINT(4, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(125, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(4185, *(uint32_t *)cotVector_Back(&vector));
}

void test_VectorEmpty(void)
{
    uint8_t buf[20];
    cotVector_t vector;

    cotVector_Init(&vector, buf, sizeof(buf), sizeof(int));

    TEST_ASSERT_TRUE(cotVector_Empty(&vector));

    int data = 42;
    cotVector_Push(&vector, &data);
    TEST_ASSERT_FALSE(cotVector_Empty(&vector));
}

void test_VectorSize(void)
{
    uint8_t buf[10];
    cotVector_t vector;

    cotVector_Init(&vector, buf, sizeof(buf), sizeof(uint32_t));
    TEST_ASSERT_EQUAL_UINT(0, cotVector_Size(&vector));

    uint32_t data = 42;
    cotVector_Push(&vector, &data);
    cotVector_Push(&vector, &data);
    TEST_ASSERT_EQUAL_UINT(2, cotVector_Size(&vector));
}

void test_VectorFront(void)
{
    uint8_t buf[20];
    cotVector_t vector;

    cotVector_Init(&vector, buf, sizeof(buf), sizeof(uint32_t));

    uint32_t data = 42;
    cotVector_Push(&vector, &data);
    data = 56;
    cotVector_Push(&vector, &data);
    TEST_ASSERT_EQUAL_UINT(2, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(42, *(uint32_t *)cotVector_Front(&vector));
}

void test_VectorBack(void)
{
    uint8_t buf[20];
    cotVector_t vector;

    cotVector_Init(&vector, buf, sizeof(buf), sizeof(uint32_t));

    uint32_t data = 42;
    cotVector_Push(&vector, &data);
    data = 56;
    cotVector_Push(&vector, &data);
    TEST_ASSERT_EQUAL_UINT(2, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(56, *(uint32_t *)cotVector_Back(&vector));
}

void test_VectorAt(void)
{
    uint8_t buf[20];
    cotVector_t vector;

    cotVector_Init(&vector, buf, sizeof(buf), sizeof(uint32_t));

    uint32_t data = 42;
    cotVector_Push(&vector, &data);
    data = 56;
    cotVector_Push(&vector, &data);
    data = 984;
    cotVector_Push(&vector, &data);
    TEST_ASSERT_EQUAL_UINT(3, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(56, *(uint32_t *)cotVector_At(&vector, 1));
}

void test_VectorClear(void)
{
    uint8_t buf[20];
    cotVector_t vector;

    cotVector_Init(&vector, buf, sizeof(buf), sizeof(uint32_t));

    uint32_t data = 42;
    cotVector_Push(&vector, &data);
    data = 56;
    cotVector_Push(&vector, &data);
    data = 984;
    cotVector_Push(&vector, &data);
    data = 163;
    cotVector_Push(&vector, &data);
    data = 159;
    cotVector_Push(&vector, &data);
    data = 4563;
    cotVector_Push(&vector, &data);
    TEST_ASSERT_EQUAL_UINT(5, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(42, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(159, *(uint32_t *)cotVector_Back(&vector));

    cotVector_Clear(&vector);

    TEST_ASSERT_EQUAL_UINT(0, cotVector_Size(&vector));
    data = 4556;
    cotVector_Push(&vector, &data);
    data = 782;
    cotVector_Push(&vector, &data);
    data = 454;
    cotVector_Push(&vector, &data);
    TEST_ASSERT_EQUAL_UINT(3, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(4556, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(454, *(uint32_t *)cotVector_Back(&vector));
}

void test_VectorInsert(void)
{
    uint8_t buf[20];
    cotVector_t vector;

    cotVector_Init(&vector, buf, sizeof(buf), sizeof(uint32_t));

    uint32_t data = 42;
    cotVector_Push(&vector, &data);
    data = 56;
    cotVector_Push(&vector, &data);
    data = 984;
    cotVector_Push(&vector, &data);
    data = 163;
    cotVector_Push(&vector, &data);
    TEST_ASSERT_EQUAL_UINT(4, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(42, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(163, *(uint32_t *)cotVector_Back(&vector));

    data = 888;
    cotVector_Insert(&vector, 2, &data);
    TEST_ASSERT_EQUAL_UINT(5, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(42, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(163, *(uint32_t *)cotVector_Back(&vector));
    TEST_ASSERT_EQUAL_UINT(888, *(uint32_t *)cotVector_At(&vector, 2));

    cotVector_Pop(&vector);
    cotVector_Pop(&vector);

    data = 999;
    cotVector_Insert(&vector, 2, &data);
    TEST_ASSERT_EQUAL_UINT(4, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(888, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(163, *(uint32_t *)cotVector_Back(&vector));
    TEST_ASSERT_EQUAL_UINT(999, *(uint32_t *)cotVector_At(&vector, 2));
}

void test_VectorInsertMutils(void)
{
    uint8_t buf[20];
    cotVector_t vector;

    cotVector_Init(&vector, buf, sizeof(buf), sizeof(uint32_t));

    uint32_t data = 42;
    cotVector_Push(&vector, &data);
    data = 56;
    cotVector_Push(&vector, &data);
    data = 984;
    cotVector_Push(&vector, &data);
    data = 163;
    cotVector_Push(&vector, &data);
    TEST_ASSERT_EQUAL_UINT(4, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(42, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(163, *(uint32_t *)cotVector_Back(&vector));

    uint32_t arrdata[2] = {125, 656};
    cotVector_InsertN(&vector, 2, &arrdata, 2);
    TEST_ASSERT_EQUAL_UINT(4, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(42, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(163, *(uint32_t *)cotVector_Back(&vector));

    cotVector_Pop(&vector);

    cotVector_InsertN(&vector, 2, &arrdata, 2);
    TEST_ASSERT_EQUAL_UINT(5, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(56, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(163, *(uint32_t *)cotVector_Back(&vector));
    TEST_ASSERT_EQUAL_UINT(125, *(uint32_t *)cotVector_At(&vector, 2));
    TEST_ASSERT_EQUAL_UINT(656, *(uint32_t *)cotVector_At(&vector, 3));
}

void test_VectorRemove(void)
{
    uint8_t buf[20];
    cotVector_t vector;

    cotVector_Init(&vector, buf, sizeof(buf), sizeof(uint32_t));

    uint32_t data = 42;
    cotVector_Push(&vector, &data);
    data = 56;
    cotVector_Push(&vector, &data);
    data = 984;
    cotVector_Push(&vector, &data);
    data = 163;
    cotVector_Push(&vector, &data);
    TEST_ASSERT_EQUAL_UINT(4, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(42, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(163, *(uint32_t *)cotVector_Back(&vector));

    cotVector_Remove(&vector, 2);
    TEST_ASSERT_EQUAL_UINT(3, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(42, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(163, *(uint32_t *)cotVector_Back(&vector));

    cotVector_Remove(&vector, 0);
    TEST_ASSERT_EQUAL_UINT(2, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(56, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(163, *(uint32_t *)cotVector_Back(&vector));

    cotVector_Remove(&vector, 1);
    TEST_ASSERT_EQUAL_UINT(1, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(56, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(56, *(uint32_t *)cotVector_Back(&vector));

    cotVector_Remove(&vector, 0);
    TEST_ASSERT_EQUAL_UINT(0, cotVector_Size(&vector));
}

void test_VectorRemoveMutils(void)
{
    uint8_t buf[20];
    cotVector_t vector;

    cotVector_Init(&vector, buf, sizeof(buf), sizeof(uint32_t));

    uint32_t data = 42;
    cotVector_Push(&vector, &data);
    data = 56;
    cotVector_Push(&vector, &data);
    data = 984;
    cotVector_Push(&vector, &data);
    data = 163;
    cotVector_Push(&vector, &data);
    TEST_ASSERT_EQUAL_UINT(4, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(42, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(163, *(uint32_t *)cotVector_Back(&vector));

    cotVector_RemoveN(&vector, 1, 2);
    TEST_ASSERT_EQUAL_UINT(2, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(42, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(163, *(uint32_t *)cotVector_Back(&vector));

    cotVector_RemoveN(&vector, 0, 3);
    TEST_ASSERT_EQUAL_UINT(2, cotVector_Size(&vector));

    cotVector_RemoveN(&vector, 0, 2);
    TEST_ASSERT_EQUAL_UINT(0, cotVector_Size(&vector));
}

bool OnVectorRemoveCondition(const void *pData)
{
    uint32_t *pVal = (uint32_t *)pData;

    if (*pVal < 100)
    {
        return true;
    }

    return false;
}

void test_VectorRemoveIf(void)
{
    uint8_t buf[20];
    cotVector_t vector;

    cotVector_Init(&vector, buf, sizeof(buf), sizeof(uint32_t));

    uint32_t data = 42;
    cotVector_Push(&vector, &data);
    data = 56;
    cotVector_Push(&vector, &data);
    data = 984;
    cotVector_Push(&vector, &data);
    data = 163;
    cotVector_Push(&vector, &data);
    TEST_ASSERT_EQUAL_UINT(4, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(42, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(163, *(uint32_t *)cotVector_Back(&vector));

    cotVector_RemoveIf(&vector, OnVectorRemoveCondition);
    TEST_ASSERT_EQUAL_UINT(2, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(984, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(163, *(uint32_t *)cotVector_Back(&vector));
}

void test_VectorData(void)
{
    uint8_t buf[20];
    cotVector_t vector;

    cotVector_Init(&vector, buf, sizeof(buf), sizeof(uint32_t));

    uint32_t data = 0x12;
    cotVector_Push(&vector, &data);
    data = 0x2568;
    cotVector_Push(&vector, &data);
    data = 0x78931236;
    cotVector_Push(&vector, &data);

    TEST_ASSERT_EQUAL_UINT8(0x12, cotVector_Data(&vector)[0]);
    TEST_ASSERT_EQUAL_UINT8(0x68, cotVector_Data(&vector)[4]);
    TEST_ASSERT_EQUAL_UINT8(0x25, cotVector_Data(&vector)[5]);
    TEST_ASSERT_EQUAL_UINT8(0x36, cotVector_Data(&vector)[8]);
    TEST_ASSERT_EQUAL_UINT8(0x12, cotVector_Data(&vector)[9]);
    TEST_ASSERT_EQUAL_UINT8(0x93, cotVector_Data(&vector)[10]);
    TEST_ASSERT_EQUAL_UINT8(0x78, cotVector_Data(&vector)[11]);
}

void test_VectorPush(void)
{
    uint8_t buf[20];
    cotVector_t vector;

    cotVector_Init(&vector, buf, sizeof(buf), sizeof(uint32_t));

    uint32_t data = 42;
    cotVector_Push(&vector, &data);
    data = 56;
    cotVector_Push(&vector, &data);
    data = 984;
    cotVector_Push(&vector, &data);
    data = 163;
    cotVector_Push(&vector, &data);
    data = 159;
    cotVector_Push(&vector, &data);
    data = 4563;
    cotVector_Push(&vector, &data);
    TEST_ASSERT_EQUAL_UINT(5, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(42, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(159, *(uint32_t *)cotVector_Back(&vector));
}

void test_VectorPop(void)
{
    uint8_t buf[20];
    cotVector_t vector;

    cotVector_Init(&vector, buf, sizeof(buf), sizeof(uint32_t));

    uint32_t data = 42;
    cotVector_Push(&vector, &data);
    data = 56;
    cotVector_Push(&vector, &data);
    data = 984;
    cotVector_Push(&vector, &data);
    data = 163;
    cotVector_Push(&vector, &data);
    data = 159;
    cotVector_Push(&vector, &data);
    data = 4563;
    cotVector_Push(&vector, &data);
    TEST_ASSERT_EQUAL_UINT(5, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(42, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(159, *(uint32_t *)cotVector_Back(&vector));

    cotVector_Pop(&vector);
    TEST_ASSERT_EQUAL_UINT(4, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(56, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(159, *(uint32_t *)cotVector_Back(&vector));

    cotVector_Pop(&vector);
    cotVector_Pop(&vector);
    cotVector_Pop(&vector);
    cotVector_Pop(&vector);
    TEST_ASSERT_EQUAL_UINT(0, cotVector_Size(&vector));
    TEST_ASSERT_NULL(cotVector_Front(&vector));
    TEST_ASSERT_NULL(cotVector_Back(&vector));
}

void test_VectorMutilsPushAndPop(void)
{
    uint8_t buf[20];
    cotVector_t vector;

    cotVector_Init(&vector, buf, sizeof(buf), sizeof(uint32_t));

    uint32_t data = 42;
    cotVector_Push(&vector, &data);
    data = 56;
    cotVector_Push(&vector, &data);
    data = 984;
    cotVector_Push(&vector, &data);
    data = 163;
    cotVector_Push(&vector, &data);

    cotVector_Pop(&vector);
    cotVector_Pop(&vector);
    cotVector_Pop(&vector);

    data = 159;
    cotVector_Push(&vector, &data);
    data = 4563;
    cotVector_Push(&vector, &data);
    data = 7834;
    cotVector_Push(&vector, &data);

    TEST_ASSERT_EQUAL_UINT(4, cotVector_Size(&vector));
    TEST_ASSERT_EQUAL_UINT(163, *(uint32_t *)cotVector_Front(&vector));
    TEST_ASSERT_EQUAL_UINT(7834, *(uint32_t *)cotVector_Back(&vector));
    TEST_ASSERT_EQUAL_UINT(4563, *(uint32_t *)cotVector_At(&vector, 2));
}


void test_VectorSwap(void)
{
    cotVector_t vector1;
    uint8_t buf1[20];

    cotVector_Init(&vector1, buf1, sizeof(buf1), sizeof(uint32_t));

    cotVector_t vector2;
    uint8_t buf2[20];

    cotVector_Init(&vector2, buf2, sizeof(buf2), sizeof(uint32_t));

    uint32_t data = 42;
    cotVector_Push(&vector1, &data);
    data = 56;
    cotVector_Push(&vector1, &data);
    data = 984;
    cotVector_Push(&vector1, &data);

    data = 163;
    cotVector_Push(&vector2, &data);

    cotVector_Swap(&vector1, &vector2);

    TEST_ASSERT_EQUAL_INT(1, cotVector_Size(&vector1));
    TEST_ASSERT_EQUAL_UINT(163, *(uint32_t *)cotVector_Front(&vector1));
    TEST_ASSERT_EQUAL_UINT(163, *(uint32_t *)cotVector_Back(&vector1));
    TEST_ASSERT_EQUAL_UINT(163, *(uint32_t *)cotVector_At(&vector1, 0));
    TEST_ASSERT_NULL(cotVector_At(&vector1, 1));

    TEST_ASSERT_EQUAL_INT(3, cotVector_Size(&vector2));
    TEST_ASSERT_EQUAL_UINT(42, *(uint32_t *)cotVector_Front(&vector2));
    TEST_ASSERT_EQUAL_UINT(984, *(uint32_t *)cotVector_Back(&vector2));
    TEST_ASSERT_EQUAL_UINT(984, *(uint32_t *)cotVector_At(&vector2, 2));
}

void test_VectorSwapEmpty(void)
{
    cotVector_t vector1;
    uint8_t buf1[20];

    cotVector_Init(&vector1, buf1, sizeof(buf1), sizeof(uint32_t));

    cotVector_t vector2;
    uint8_t buf2[20];

    cotVector_Init(&vector2, buf2, sizeof(buf2), sizeof(uint32_t));

    cotVector_Swap(&vector1, &vector2);

    TEST_ASSERT_EQUAL_INT(0, cotVector_Size(&vector1));
    TEST_ASSERT_NULL(cotVector_Front(&vector1));
    TEST_ASSERT_NULL(cotVector_Back(&vector1));
    TEST_ASSERT_NULL(cotVector_At(&vector1, 0));

    TEST_ASSERT_EQUAL_INT(0, cotVector_Size(&vector2));
    TEST_ASSERT_NULL(cotVector_Front(&vector2));
    TEST_ASSERT_NULL(cotVector_Back(&vector2));
    TEST_ASSERT_NULL(cotVector_At(&vector2, 2));
}

void test_VectorSwapNonEmptyAndEmpty(void)
{
    cotVector_t vector1;
    uint8_t buf1[20];

    cotVector_Init(&vector1, buf1, sizeof(buf1), sizeof(uint32_t));

    cotVector_t vector2;
    uint8_t buf2[20];

    cotVector_Init(&vector2, buf2, sizeof(buf2), sizeof(uint32_t));

    uint32_t data = 42;
    cotVector_Push(&vector1, &data);
    data = 56;
    cotVector_Push(&vector1, &data);
    data = 984;
    cotVector_Push(&vector1, &data);

    cotVector_Swap(&vector1, &vector2);

    TEST_ASSERT_EQUAL_INT(0, cotVector_Size(&vector1));
    TEST_ASSERT_NULL(cotVector_Front(&vector1));
    TEST_ASSERT_NULL(cotVector_Back(&vector1));
    TEST_ASSERT_NULL(cotVector_At(&vector1, 0));

    TEST_ASSERT_EQUAL_INT(3, cotVector_Size(&vector2));
    TEST_ASSERT_EQUAL_UINT(42, *(uint32_t *)cotVector_Front(&vector2));
    TEST_ASSERT_EQUAL_UINT(984, *(uint32_t *)cotVector_Back(&vector2));
    TEST_ASSERT_EQUAL_UINT(984, *(uint32_t *)cotVector_At(&vector2, 2));
}



int test_Vector(void)
{
    UNITY_BEGIN();  // 初始化 Unity 测试框架

    RUN_TEST(test_VectorInit);
    RUN_TEST(test_VectorAssign);
    RUN_TEST(test_VectorEmpty);
    RUN_TEST(test_VectorSize);
    RUN_TEST(test_VectorFront);
    RUN_TEST(test_VectorBack);
    RUN_TEST(test_VectorAt);
    RUN_TEST(test_VectorData);
    RUN_TEST(test_VectorClear);
    RUN_TEST(test_VectorInsert);
    RUN_TEST(test_VectorInsertMutils);
    RUN_TEST(test_VectorRemove);
    RUN_TEST(test_VectorRemoveMutils);
    RUN_TEST(test_VectorRemoveIf);
    RUN_TEST(test_VectorPush);
    RUN_TEST(test_VectorPop);
    RUN_TEST(test_VectorMutilsPushAndPop);
    RUN_TEST(test_VectorSwap);
    RUN_TEST(test_VectorSwapEmpty);
    RUN_TEST(test_VectorSwapNonEmptyAndEmpty);
    

    UNITY_END();  // 结束测试

    return 0;
}
